home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / glibc108.zip / glibc108 / stdio / memstream.c < prev    next >
C/C++ Source or Header  |  1992-08-07  |  5KB  |  178 lines

  1. /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ansidecl.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. struct memstream_info
  25.   {
  26.     char **buffer;
  27.     size_t *bufsize;
  28.   };
  29.  
  30. /* Enlarge STREAM's buffer.  */
  31. static void
  32. DEFUN(enlarge_buffer, (stream, c),
  33.       register FILE *stream AND int c)
  34. {
  35.   struct memstream_info *info = (struct memstream_info *) stream->__cookie;
  36.   size_t need;
  37.  
  38.   if (stream->__put_limit != stream->__buffer)
  39.     /* Record how much has actually been written into the buffer.  */
  40.     *info->bufsize = stream->__bufp - stream->__buffer;
  41.  
  42.   if (stream->__target != -1
  43.       && stream->__target > *info->bufsize)
  44.     /* Our target (where the buffer maps to) is always zero except when
  45.        the user just did a SEEK_END fseek.  If he sought within the
  46.        buffer, we need do nothing and will zero the target below.  If he
  47.        sought past the end of the object, grow and zero-fill the buffer
  48.        up to the target address.  */
  49.     need = stream->__target;
  50.   else
  51.     need = *info->bufsize + (c == EOF ? 0 : 1);
  52.  
  53.   if (stream->__bufsize < need)
  54.     {
  55.       /* Enlarge the buffer.  */
  56.       char *newbuf;
  57.       if (stream->__bufsize * 2 < need)
  58.     stream->__bufsize = need;
  59.       else
  60.     stream->__bufsize *= 2;
  61.       newbuf = (char *) realloc ((PTR) stream->__buffer, stream->__bufsize);
  62.       *info->buffer = newbuf;
  63.       if (newbuf == NULL)
  64.     {
  65.       free ((PTR) stream->__buffer);
  66.       stream->__buffer = stream->__bufp
  67.         = stream->__put_limit = stream->__get_limit = NULL;
  68.       stream->__error = 1;
  69.       return;
  70.     }
  71.       stream->__buffer = newbuf;
  72.     }
  73.  
  74.   stream->__target = stream->__offset = 0;
  75.   stream->__get_limit = stream->__bufp = stream->__buffer + *info->bufsize;
  76.   stream->__put_limit = stream->__buffer + stream->__bufsize;
  77.  
  78.   need -= stream->__bufp - stream->__buffer;
  79.   if (c != EOF)
  80.     --need;
  81.   if (need > 0)
  82.     {
  83.       /* We are extending the buffer after an fseek; zero-fill new space.  */
  84.       bzero (stream->__bufp, need);
  85.       stream->__bufp += need;
  86.     }
  87.  
  88.   if (c != EOF)
  89.     *stream->__bufp++ = (unsigned char) c;
  90.   else
  91.     *stream->__bufp = '\0';
  92. }
  93.  
  94. /* Seek function for memstreams.
  95.    There is no external state to munge.  */
  96.  
  97. static int
  98. DEFUN(seek, (cookie, pos, whence),
  99.       PTR cookie AND fpos_t *pos AND int whence)
  100. {
  101.   switch (whence)
  102.     {
  103.     case SEEK_SET:
  104.     case SEEK_CUR:
  105.       return 0;
  106.  
  107.     case SEEK_END:
  108.       /* Return the position relative to the end of the object.
  109.      fseek has just flushed us, so the info is consistent.  */
  110.       *pos += *((struct memstream_info *) cookie)->bufsize;
  111.       return 0;
  112.  
  113.     default:
  114.       __libc_fatal ("memstream::seek called with bogus WHENCE\n");
  115.       return -1;
  116.     }
  117. }
  118.  
  119. static int
  120. DEFUN(free_info, (cookie), PTR cookie)
  121. {
  122. #if 0
  123.   struct memstream_info *info = (struct memstream_info *) cookie;
  124.   char *buf;
  125.  
  126.   buf = (char *) realloc ((PTR) *info->buffer, *info->bufsize);
  127.   if (buf != NULL)
  128.     *info->buffer = buf;
  129. #endif
  130.  
  131.   free (cookie);
  132.  
  133.   return 0;
  134. }
  135.  
  136. /* Open a stream that writes into a malloc'd buffer that is expanded as
  137.    necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
  138.    and the number of characters written on fflush or fclose.  */
  139. FILE *
  140. DEFUN(open_memstream, (bufloc, sizeloc),
  141.       char **bufloc AND size_t *sizeloc)
  142. {
  143.   FILE *stream;
  144.   struct memstream_info *info;
  145.  
  146.   if (bufloc == NULL || sizeloc == NULL)
  147.     {
  148.       errno = EINVAL;
  149.       return NULL;
  150.     }
  151.  
  152.   stream = fmemopen ((char *) NULL, BUFSIZ, "w+");
  153.   if (stream == NULL)
  154.     return NULL;
  155.  
  156.   info = (struct memstream_info *) malloc (sizeof (struct memstream_info));
  157.   if (info == NULL)
  158.     {
  159.       int save = errno;
  160.       (void) fclose (stream);
  161.       errno = save;
  162.       return NULL;
  163.     }
  164.  
  165.   stream->__room_funcs.__output = enlarge_buffer;
  166.   stream->__io_funcs.__seek = seek;
  167.   stream->__io_funcs.__close = free_info;
  168.   stream->__cookie = (PTR) info;
  169.   stream->__userbuf = 1;
  170.  
  171.   info->buffer = bufloc;
  172.   info->bufsize = sizeloc;
  173.  
  174.   *bufloc = stream->__buffer;
  175.  
  176.   return stream;
  177. }
  178.